package ru.paswd.compare.rest;

import lombok.Getter;

import java.util.ArrayList;
import java.util.List;

public class Matrix {

    @Getter
    private List<List<Double>> data;

    @Getter
    private int width = 0;

    @Getter
    private int height = 0;

    public Matrix(List<List<Double>> matrix) throws IncorrectMatrixException {
        init(matrix);
    }

    public Matrix(int i, int j) {
        init(i, j);
    }

    public void init(List<List<Double>> matrix) throws IncorrectMatrixException {
        receiveWidthAndHeight(matrix);
        data = matrix;
    }

    public void init(int i, int j) {
        height = i;
        width = j;

        data = new ArrayList<>();

        for (int ci = 0; ci < i; ci++) {
            List<Double> newItem = new ArrayList<>();

            for (int cj = 0; cj < j; cj++)
                newItem.add(0.);

            data.add(newItem);
        }
    }

    public Double get(int i, int j) {
        return data.get(i).get(j);
    }

    private void receiveWidthAndHeight(List<List<Double>> matrix) throws IncorrectMatrixException {
        int currentHeight = matrix.size();
        int currentWidth = currentHeight > 0 ? matrix.get(0).size() : 0;

        validate(matrix, currentHeight, currentWidth);

        this.height = currentHeight;
        this.width = currentWidth;
    }

    private void validate(List<List<Double>> matrix,
                          final int height, final int width) throws IncorrectMatrixException {

        if (height > 0 && width == 0)
            throw new IncorrectMatrixException();

        if (matrix.size() != height)
            throw new IncorrectMatrixException();

        matrix.forEach(row -> {
            if (row.size() != width)
                throw new IncorrectMatrixException();
        });
    }

    public static Matrix multiply(Matrix matrix1, Matrix matrix2) throws MatrixMultiplicationException {
        if (matrix1.width != matrix2.height)
            throw new MatrixMultiplicationException();

        Matrix newMatrix = new Matrix(matrix1.height, matrix2.width);

        for (int i = 0; i < matrix1.height; i++) {
            for (int j = 0; j < matrix2.width; j++) {
                double current = 0;

                for (int k = 0; k < matrix1.width; k++)
                    current += matrix1.get(i, k) * matrix2.get(k, j);

                newMatrix.data.get(i).set(j, current);
            }
        }

        return newMatrix;
    }
}
